<template>
  <div class="test-currency-item">
    <div class="top-row">
      <img class="coin-logo" :src="currencyItem.logo" alt="logo" />
      <div class="coin-info">
        <div class="coin-symbol">{{ currencyItem.coinUpperCase }}</div>
        <div class="coin-base">USD</div>
      </div>
    </div>
    <div class="chart-row">
      <svg class="line-chart" viewBox="0 0 100 40" preserveAspectRatio="none">
        <path :d="pathData" stroke="#00b386" fill="none" stroke-width="1" stroke-linecap="round" />
      </svg>
    </div>
    <div class="price-row">
      <span class="price">${{ animatedPrice }}</span>
      <span :class="['change', changeUp ? 'up' : 'down']">
        <span v-if="changeUp">▲</span><span v-else>▼</span>
        {{ animatedPercent }}%
      </span>
    </div>
    <div class="btn-row">
      <button class="btn buy">买涨</button>
      <button class="btn sell">买跌</button>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'

const props = defineProps({
  currencyItem: {
    type: Object,
    default: () => ({})
  }
})

// 动画相关
const animatedPrice = ref(0)
const animatedPercent = ref(0)
let priceFrame = null
let percentFrame = null
const animationDuration = 800

function animateValue(refVal, start, end, duration, formatFn) {
  const startTime = Date.now()
  function animate() {
    const progress = Math.min((Date.now() - startTime) / duration, 1)
    const currentVal = start + (end - start) * progress
    refVal.value = formatFn ? formatFn(currentVal) : currentVal
    if (progress < 1) {
      requestAnimationFrame(animate)
    } else {
      refVal.value = formatFn ? formatFn(end) : end
    }
  }
  animate()
}

function priceFormat(val) {
  return Number(val).toLocaleString(undefined, { maximumFractionDigits: 6 })
}

function percentFormat(val) {
  return Number(val).toFixed(2)
}

function getPercent(amount, open) {
  if (!amount || !open) return 0
  return ((amount - open) / open * 100)
}

// 监听价格变化
watch(() => props.currencyItem.amount, (newVal, oldVal) => {
  if (priceFrame) cancelAnimationFrame(priceFrame)
  animateValue(animatedPrice, oldVal || 0, newVal || 0, animationDuration, priceFormat)
}, { immediate: true })

// 监听涨跌幅变化
watch([
  () => props.currencyItem.amount,
  () => props.currencyItem.open
], ([newAmount, newOpen], [oldAmount, oldOpen]) => {
  const oldPercent = getPercent(oldAmount, oldOpen)
  const newPercent = getPercent(newAmount, newOpen)
  if (percentFrame) cancelAnimationFrame(percentFrame)
  animateValue(animatedPercent, oldPercent, newPercent, animationDuration, percentFormat)
}, { immediate: true })

const changeUp = computed(() => Number(animatedPercent.value) >= 0)

// 动态折线图
const pathData = ref('')
let pathTimer = null
function generatePath() {
  try {
    const points = []
    const segments = 6
    const baseY = 20
    for(let i = 0; i <= segments; i++) {
      const x = (i * 100) / segments
      const y = baseY + (Math.random() * 36 - 18)
      points.push({x, y})
    }
    let path = `M ${points[0].x} ${points[0].y} `
    points.forEach((point, index) => {
      if(index > 0) {
        const prev = points[index - 1]
        const cp1x = prev.x + (point.x - prev.x) * 0.2
        const cp1y = prev.y + (Math.random() * 15 - 7.5)
        const cp2x = prev.x + (point.x - prev.x) * 0.8
        const cp2y = point.y + (Math.random() * 15 - 7.5)
        path += `C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${point.x} ${point.y} `
      }
    })
    return path
  } catch {
    return "M 0 20 C 20 15, 30 25, 50 20 S 80 15, 100 20"
  }
}
onMounted(() => {
  pathData.value = generatePath()
  pathTimer = setInterval(() => {
    pathData.value = generatePath()
  }, 3000)
})
onUnmounted(() => {
  clearInterval(pathTimer)
  if (priceFrame) cancelAnimationFrame(priceFrame)
  if (percentFrame) cancelAnimationFrame(percentFrame)
})
</script>

<style lang="scss" scoped>
.test-currency-item {
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.06);
  padding: 16px 12px 12px 12px;
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
  box-sizing: border-box;

  .top-row {
    display: flex;
    align-items: center;
    width: 100%;
    margin-bottom: 6px;
    .coin-logo {
      width: 38px;
      height: 38px;
      border-radius: 50%;
      background: #f5f5f5;
      margin-right: 8px;
      border: 2px solid #fff;
      box-shadow: 0 1px 4px rgba(0,0,0,0.04);
    }
    .coin-info {
      display: flex;
      flex-direction: column;
      .coin-symbol {
        font-size: 18px;
        font-weight: bold;
        color: #222;
        line-height: 1.1;
      }
      .coin-base {
        font-size: 12px;
        color: #888;
        margin-top: 2px;
      }
    }
  }
  .chart-row {
    width: 100%;
    height: 54px;
    margin: 8px 0 0 0;
    .line-chart {
      width: 100%;
      height: 100%;
      display: block;
      path {
        transition: d 0.8s cubic-bezier(0.4, 0, 0.2, 1);
      }
    }
  }
  .price-row {
    width: 100%;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin: 10px 0 0 0;
    .price {
      font-size: 12px;
      font-weight: 900;
      color: #000 !important;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      max-width:70px;
    }
    .change {
      font-size: 12px;
      font-weight: 600;
      margin-left: 8px;
      &.up {
        color: #00b386;
      }
      &.down {
        color: #ff4444;
      }
    }
  }
  .btn-row {
    width: 100%;
    display: flex;
    justify-content: space-between;
    margin-top: 14px;
    .btn {
      flex: 1;
      font-size: 12px;
      font-weight: 600;
      border: none;
      border-radius: 6px;
      padding: 7px 0;
      margin: 0 4px;
      color: #fff;
      cursor: pointer;
      &.buy {
        background: #00b386;
      }
      &.sell {
        background: #ff4444;
      }
    }
    .btn:first-child { margin-left: 0; }
    .btn:last-child { margin-right: 0; }
  }
}
</style> 